/*
 * This file is part of aion-unique <aion-unique.org>.
 *
 *  aion-unique is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  aion-unique is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with aion-unique.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.aionemu.gameserver.model.team.legion;

import java.nio.ByteBuffer;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import javolution.util.FastList;
import javolution.util.FastMap;

import org.apache.log4j.Logger;

import com.aionemu.commons.database.dao.DAOManager;
import com.aionemu.gameserver.configs.main.LegionConfig;
import com.aionemu.gameserver.dao.LegionDAO;
import com.aionemu.gameserver.model.Race;
import com.aionemu.gameserver.model.gameobjects.Item;
import com.aionemu.gameserver.model.gameobjects.Npc;
import com.aionemu.gameserver.model.gameobjects.PersistentState;
import com.aionemu.gameserver.model.gameobjects.VisibleObject;
import com.aionemu.gameserver.model.gameobjects.player.DeniedStatus;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.player.RequestResponseHandler;
import com.aionemu.gameserver.model.gameobjects.player.StorageType;
import com.aionemu.gameserver.model.team.Team;
import com.aionemu.gameserver.model.team.interfaces.ITeamMember;
import com.aionemu.gameserver.model.team.legion.enums.eLegionEditEvent;
import com.aionemu.gameserver.model.team.legion.enums.eLegionHistoryType;
import com.aionemu.gameserver.model.team.legion.enums.eLegionRight;
import com.aionemu.gameserver.network.aion.serverpackets.SM_DIALOG_WINDOW;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_ADD_MEMBER;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_EDIT;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_EMBLEM_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_EMBLEM_SHOW;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_LEAVE_MEMBER;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_MEMBERLIST;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_TABS;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_UPDATE_EMBLEM;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_UPDATE_NICKNAME;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_UPDATE_SELF_INTRO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEGION_UPDATE_TITLE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_QUESTION_WINDOW;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_WAREHOUSE_INFO;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.idfactory.IDFactory;
import com.aionemu.gameserver.world.World;

/**
 * @author Simple
 * 
 */
public class Legion extends Team<LegionMember> implements ITeamMember
{
	private static final Logger					log	= Logger.getLogger(Legion.class);

	private static HashMap<Integer, Integer>	legionRanking;

	public static HashMap<Integer, Integer> getLegionRanking()
	{
		return legionRanking;
	}

	public static void setLegionRanking(HashMap<Integer, Integer> legionRanking)
	{
		Legion.legionRanking = legionRanking;
	}

	private static class LegionRankingUpdateTask implements Runnable
	{
		@Override
		public void run()
		{
			log.info("Legion ranking update task started");
			long startTime = System.currentTimeMillis();
			int legionsUpdated = 0;
			Collection<Legion> legions = new FastList<Legion>();
			for (Team<?> memb : teams.values())
			{
				if (memb instanceof Legion)
					legions.add((Legion) memb);
			}

			setLegionRanking(DAOManager.getDAO(LegionDAO.class).loadLegionRanking());

			for (Legion legion : legions)
			{
				try
				{
					if (legionRanking.containsKey(legion.getObjectId()))
					{
						legion.setLegionRank(legionRanking.get(legion.getObjectId()));
						PacketSendUtility.broadcastPacketToTeam(null, legion, new SM_LEGION_EDIT(eLegionEditEvent.CHANGE_RANK, legion));
					}
				}
				catch (Exception ex)
				{
					log.error("Exception during periodic update of legion ranking " + ex.getMessage());
				}

				legionsUpdated++;
			}
			long workTime = System.currentTimeMillis() - startTime;
			log.info("Legion ranking update: " + workTime + " ms, legions: " + legionsUpdated);
		}
	}

	public static Legion getLegionById(int id)
	{
		return (Legion) getTeamById(id);
	}

	public static Legion getLegionByName(String name)
	{
		for (Team<?> memb : teams.values())
		{
			if (memb instanceof Legion)
				if (((Legion) memb).getName().equalsIgnoreCase(name))
					return (Legion) memb;
		}
		return null;
	}

	public static void LoadLegions()
	{
		DAOManager.getDAO(LegionDAO.class).loadLegions();
		new LegionRankingUpdateTask().run();
	}

	/**
	 * This method will handle the creation of a legion
	 * 
	 * @param activePlayer
	 * @param legionName
	 */
	public static void createLegion(Player activePlayer, String legionName)
	{
		if (canCreateLegion(activePlayer, legionName))
		{
			/**
			 * Create new legion and put originator as first member
			 */
			Legion legion = new Legion(IDFactory.getInstance().nextId(), activePlayer.getObjectId(), legionName, true);
			Item.decreaseKinah(activePlayer, LegionConfig.LEGION_CREATE_REQUIRED_KINAH);

			/**
			 * Add create and joined legion history and save it
			 */
			legion.addHistory("", eLegionHistoryType.CREATE);
			legion.addHistory(activePlayer.getName(), eLegionHistoryType.JOIN);

			/**
			 * Send required packets
			 */
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CREATED(legion.getName()));
		}
	}

	/**
	 * This method checks all restrictions for legion creation
	 * 
	 * @param activePlayer
	 * @param legionName
	 * @return true if allow to create a legion
	 */
	private static boolean canCreateLegion(Player activePlayer, String legionName)
	{
		/* Some reasons why legions can' be created */
		if (!isValidName(legionName))
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CREATE_INVALID_NAME());
			return false;
		}
		else if (!isFreeName(legionName))
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CREATE_NAME_EXISTS());
			return false;
		}
		else if (activePlayer.getLegion() != null)
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CREATE_ALREADY_MEMBER());
			return false;
		}
		else if (activePlayer.getInventory().getKinahItem().getItemCount() < LegionConfig.LEGION_CREATE_REQUIRED_KINAH)
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CREATE_NOT_ENOUGH_KINAH());
			return false;
		}
		return true;
	}

	public static boolean isValidName(String name)
	{
		return LegionConfig.LEGION_NAME_PATTERN.matcher(name).matches();
	}

	private static boolean isFreeName(String name)
	{
		return !DAOManager.getDAO(LegionDAO.class).isNameUsed(name);
	}

	/** Static Permission settings **/
	private static final int			PERMISSION1_MIN				= 0x60;
	private static final int			PERMISSION2_MIN				= 0x00;
	private static final int			LEGIONAR_PERMISSION2_MAX	= 0x08;
	private static final int			CENTURION_PERMISSION1_MAX	= 0x7C;
	private static final int			CENTURION_PERMISSION2_MAX	= 0x0E;

	/** Legion Information **/
	private String						legionName					= "";
	private byte						legionLevel					= 1;
	private int							legionRank					= 0;
	private long						contributionPoints			= 0;
	private static final int			legionarPermission1			= 0x40;
	private int							legionarPermission2			= 0x00;
	private int							centurionPermission1		= 0x60;
	private int							centurionPermission2		= 0x00;
	private int							disbandTime;
	//TODO need old announcements?
	private TreeMap<Timestamp, String>	announcementList			= new TreeMap<Timestamp, String>();
	private LegionEmblem				legionEmblem;
	private LegionWarehouse				legionWarehouse;
	private SortedSet<LegionHistory>	legionHistory;
	protected Map<String, LegionMember>	membersByName				= new FastMap<String, LegionMember>().shared();

	/**
	 * Only called when a legion is created!
	 * 
	 * @param legionId
	 * @param legionName
	 */
	public Legion(int legionId, int leader, String legionName, boolean create)
	{
		super(legionId, leader);
		this.legionName = legionName;
		if (create)
		{
			this.legionWarehouse = new LegionWarehouse(this);
			this.legionEmblem = new LegionEmblem();
			this.legionHistory = new TreeSet<LegionHistory>(new Comparator<LegionHistory>()
			{
				@Override
				public int compare(LegionHistory o1, LegionHistory o2)
				{
					return o1.getTime().getTime() < o2.getTime().getTime() ? 1 : -1;
				}
			});
			DAOManager.getDAO(LegionDAO.class).saveNewLegion(this, leader);
			this.addLegionMember(World.getInstance().findPlayer(leader), LegionRank.BRIGADE_GENERAL);
		}
	}

	/**
	 * Only called when a legion is loaded!
	 * 
	 * @param legionId
	 * @param legionName
	 */
	public Legion(int legionId, int leader, String legionName, byte level, long contributionPoints, int legionarPermission2, int centurionPermission1,
			int centurionPermission2, int disbandTime, LegionEmblem emblem, SortedSet<LegionHistory> history, TreeMap<Timestamp, String> announces)
	{
		this(legionId, leader, legionName, false);
		this.legionLevel = level;
		setLegionPermissions(legionarPermission2, centurionPermission1, centurionPermission2);
		this.contributionPoints = contributionPoints;
		this.disbandTime = disbandTime;
		this.legionEmblem = emblem;
		this.legionHistory = history;
		this.announcementList = announces;
	}

	public void setName(String name)
	{
		this.legionName = name;
		PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_INFO(this));

		for (Player legionMember : getOnlineMembers())
		{
			PacketSendUtility.broadcastPacket(legionMember, new SM_LEGION_UPDATE_TITLE(getMemberById(legionMember.getObjectId())), true);
		}
		DAOManager.getDAO(LegionDAO.class).storeLegion(this);
	}

	@Override
	public void setMembers(Map<Integer, LegionMember> members)
	{
		super.setMembers(members);
		for (LegionMember member : members.values())
			membersByName.put(member.getCommondata().getName().toLowerCase(), member);
	}

	private boolean addLegionMember(Player player)
	{
		if (!isFull())
		{
			addLegionMember(player, LegionRank.LEGIONARY);
			return true;
		}
		return false;
	}

	private void addLegionMember(Player player, LegionRank rank)
	{
		LegionMember member = new LegionMember(player.getObjectId(), getObjectId(), rank, "", "");
		// Set legion member of player and save in the database
		player.setLegion(this);
		addMember(member);
		addOnlineMember(player);
		player.getObjectTemplate().setLegionId(this.getObjectId());
		DAOManager.getDAO(LegionDAO.class).saveLegionMember(member);

		// Send the new legion member the required legion packets
		PacketSendUtility.sendPacket(player, new SM_LEGION_INFO(this));

		// Send legion member info to the members
		PacketSendUtility.broadcastPacketToTeam(player, this, new SM_LEGION_ADD_MEMBER(player, false, 0, ""));

		// Send the member list to the new legion member
		PacketSendUtility.sendPacket(player, new SM_LEGION_MEMBERLIST(getMemberList()));

		// Update legion member's appearance in game
		PacketSendUtility.broadcastPacket(player, new SM_LEGION_UPDATE_TITLE(member), true);

		// Send legion emblem information
		PacketSendUtility.sendPacket(player, new SM_LEGION_UPDATE_EMBLEM(this, getLegionEmblem()));

		// Send legion edit
		PacketSendUtility.sendPacket(player, new SM_LEGION_EDIT(eLegionEditEvent.REFRESH_ANNOUNCEMENT));
	}

	public void kickMember(Player requester, String targetName)
	{
		LegionMember targetlm = getMemberByName(targetName);
		if (targetlm.getPlayer() != null)
			PacketSendUtility.broadcastPacket(targetlm.getPlayer(), new SM_LEGION_UPDATE_TITLE(targetlm.getObjectId()), true);
		if (canKickPlayer(getMemberById(requester.getObjectId()), targetlm))
		{
			deleteMemberFromLegion(targetlm);
			PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_LEAVE_MEMBER(1300247, targetlm.getObjectId(), requester.getName(), targetlm
					.getCommondata().getName()));
		}
	}

	public void leaveLegion(Player requester)
	{
		if (!getMemberById(requester.getObjectId()).getRank().equals(LegionRank.BRIGADE_GENERAL))
		{
			PacketSendUtility.sendPacket(requester, new SM_LEGION_LEAVE_MEMBER(1300241, 0, getName()));
			deleteMemberFromLegion(getMemberById(requester.getObjectId()));
			PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_LEAVE_MEMBER(900699, requester.getObjectId(), requester.getName()));
			requester.setLegion(null);
		}
		else
		{
			//TODO retail message
		}
	}

	private void deleteMemberFromLegion(LegionMember member)
	{
		DAOManager.getDAO(LegionDAO.class).deleteLegionMember(member.getObjectId());
		addHistory(member.getCommondata().getName(), eLegionHistoryType.KICK);
		removeMember(member);
		member.getCommondata().setLegionId(0);
	}

	@Override
	public void removeMember(LegionMember member)
	{
		membersByName.remove(member.getCommondata().getName());
		super.removeMember(member);
	}

	private boolean canKickPlayer(LegionMember activePlayer, LegionMember target)
	{
		if (target.equals(activePlayer))
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_CANT_KICK_YOURSELF());
			return false;
		}
		else if (target.isBrigadeGeneral())
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_CANT_KICK_BRIGADE_GENERAL());
			return false;
		}
		else if (target.getRank().equals(activePlayer.getRank()))
		{
			// Same rank so can't kick
			// TODO: Message
			return false;
		}
		else if (!isMember(target))
		{
			// Not in same legion
			return false;
		}
		else if (!activePlayer.hasRights(eLegionRight.KICK))
		{
			// No rights to kick
			return false;
		}
		return true;
	}

	/**
	 * This method will add a new history for a legion
	 * 
	 * @param legion
	 * @param legionHistory
	 */
	private void addHistory(String text, eLegionHistoryType legionHistoryType)
	{
		LegionHistory legionHistory = new LegionHistory(legionHistoryType, text, new Timestamp(System.currentTimeMillis()));

		addHistory(legionHistory);
		DAOManager.getDAO(LegionDAO.class).saveNewLegionHistory(getObjectId(), legionHistory);

		PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_TABS(getLegionHistory()));
	}

	/**
	 * This method will set the permissions
	 * 
	 * @param legionarPermission2
	 * @param centurionPermission1
	 * @param centurionPermission2
	 * @return true or false
	 */
	public boolean setLegionPermissions(int legionarPermission2, int centurionPermission1, int centurionPermission2)
	{
		if (checkPermissions(legionarPermission2, centurionPermission1, centurionPermission2))
		{
			this.legionarPermission2 = legionarPermission2;
			this.centurionPermission1 = centurionPermission1;
			this.centurionPermission2 = centurionPermission2;
			return true;
		}
		return false;
	}

	/**
	 * Check if all permissions are correct
	 * 
	 * @return true or false
	 */
	private boolean checkPermissions(int legionarPermission2, int centurionPermission1, int centurionPermission2)
	{
		if (legionarPermission2 < PERMISSION2_MIN || legionarPermission2 > LEGIONAR_PERMISSION2_MAX)
			return false;
		if (centurionPermission1 < PERMISSION1_MIN || centurionPermission1 > CENTURION_PERMISSION1_MAX)
			return false;
		if (centurionPermission2 < PERMISSION2_MIN || centurionPermission2 > CENTURION_PERMISSION2_MAX)
			return false;
		return true;
	}

	/**
	 * @return the legionarPermission1
	 */
	public int getLegionarPermission1()
	{
		return legionarPermission1;
	}

	/**
	 * @return the legionarPermission2
	 */
	public int getLegionarPermission2()
	{
		return legionarPermission2;
	}

	/**
	 * @return the centurionPermission1
	 */
	public int getCenturionPermission1()
	{
		return centurionPermission1;
	}

	/**
	 * @return the centurionPermission2
	 */
	public int getCenturionPermission2()
	{
		return centurionPermission2;
	}

	public byte getLegionLevel()
	{
		return legionLevel;
	}

	public void setLegionLevel(byte newLevel)
	{
		this.legionLevel = newLevel;
		PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_EDIT(eLegionEditEvent.CHANGE_LEVEL, this));
		PacketSendUtility.broadcastPacketToTeam(null, this, SM_SYSTEM_MESSAGE.LEGION_LEVEL_UP(newLevel));
		addHistory(String.valueOf(legionLevel), eLegionHistoryType.LEVEL_UP);
		DAOManager.getDAO(LegionDAO.class).storeLegion(this);
	}

	/**
	 * @param legionRank
	 *            the legionRank to set
	 */
	public void setLegionRank(int legionRank)
	{
		this.legionRank = legionRank;
	}

	/**
	 * @return the legionRank
	 */
	public int getLegionRank()
	{
		return legionRank;
	}

	/**
	 * @param count
	 *            the contributionPoints to set
	 */
	public void addContributionPoints(long count)
	{
		setContributionPoints(count + getContributionPoints());
	}

	/**
	 * @param newPoints
	 */
	public void setContributionPoints(long l)
	{
		this.contributionPoints = l;
		PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_EDIT(eLegionEditEvent.CHANGE_CONTRIBUTION, this));
		DAOManager.getDAO(LegionDAO.class).storeLegion(this);
	}

	public void uploadEmblemInfo(Player activePlayer, int totalSize, int colorRGB)
	{
		if (canUploadEmblemInfo(getMemberById(activePlayer.getObjectId())))
		{
			LegionEmblem legionEmblem = getLegionEmblem();
			legionEmblem.setColor_rgb(colorRGB);
			legionEmblem.setUploadSize(totalSize);
			legionEmblem.setUploading(true);
		}
	}

	private boolean canUploadEmblemInfo(LegionMember activePlayer)
	{
		// TODO: System Messages
		if (!activePlayer.isBrigadeGeneral())
			// Not legion leader
			return false;
		else if (getLegionLevel() < 3)
		{
			// Legion level isn't high enough
			return false;
		}
		else if (getLegionEmblem().isUploading())
		{
			// Already uploading emblem, reset uploading
			getLegionEmblem().setUploading(false);
			return false;
		}
		return true;
	}

	/**
	 * @return the contributionPoints
	 */
	public long getContributionPoints()
	{
		return contributionPoints;
	}

	/**
	 * This method will check whether a legion has enough members to level up
	 * 
	 * @return true or false
	 */
	public boolean hasRequiredMembers()
	{
		switch (getLegionLevel())
		{
			case 1:
				if (size() >= LegionConfig.LEGION_LEVEL2_REQUIRED_MEMBERS)
					return true;
				break;
			case 2:
				if (size() >= LegionConfig.LEGION_LEVEL3_REQUIRED_MEMBERS)
					return true;
				break;
			case 3:
				if (size() >= LegionConfig.LEGION_LEVEL4_REQUIRED_MEMBERS)
					return true;
				break;
			case 4:
				if (size() >= LegionConfig.LEGION_LEVEL5_REQUIRED_MEMBERS)
					return true;
				break;
		}
		return false;
	}

	/**
	 * This method will return the kinah price required to level up
	 * 
	 * @return int
	 */
	public int getKinahPrice()
	{
		switch (getLegionLevel())
		{
			case 1:
				return LegionConfig.LEGION_LEVEL2_REQUIRED_KINAH;
			case 2:
				return LegionConfig.LEGION_LEVEL3_REQUIRED_KINAH;
			case 3:
				return LegionConfig.LEGION_LEVEL4_REQUIRED_KINAH;
			case 4:
				return LegionConfig.LEGION_LEVEL5_REQUIRED_KINAH;
		}
		return 0;
	}

	/**
	 * This method will return the contribution points required to level up
	 * 
	 * @return int
	 */
	public int getContributionPrice()
	{
		switch (getLegionLevel())
		{
			case 1:
				return LegionConfig.LEGION_LEVEL2_REQUIRED_CONTRIBUTION;
			case 2:
				return LegionConfig.LEGION_LEVEL3_REQUIRED_CONTRIBUTION;
			case 3:
				return LegionConfig.LEGION_LEVEL4_REQUIRED_CONTRIBUTION;
			case 4:
				return LegionConfig.LEGION_LEVEL5_REQUIRED_CONTRIBUTION;
		}
		return 0;
	}

	/**
	 * @param announcementList
	 *            the announcementList to set
	 */
	public void setAnnouncementList(TreeMap<Timestamp, String> announcementList)
	{
		this.announcementList = announcementList;
	}

	/**
	 * This method will add a new announcement to the list
	 */
	public void addAnnouncementToList(Timestamp unixTime, String announcement)
	{
		this.announcementList.put(unixTime, announcement);
	}

	/**
	 * This method removes the first entry
	 */
	public void removeFirstEntry()
	{
		this.announcementList.remove(this.announcementList.firstEntry().getKey());
	}

	/**
	 * @return the announcementList
	 */
	public TreeMap<Timestamp, String> getAnnouncementList()
	{
		return this.announcementList;
	}

	/**
	 * @return the currentAnnouncement
	 */
	public Entry<Timestamp, String> getCurrentAnnouncement()
	{
		if (this.announcementList.size() > 0)
			return this.announcementList.lastEntry();
		return null;
	}

	/**
	 * @param disbandTime
	 *            the disbandTime to set
	 */
	public void setDisbandTime(int disbandTime)
	{
		this.disbandTime = disbandTime;
	}

	/**
	 * @return the disbandTime
	 */
	public int getDisbandTime()
	{
		return disbandTime;
	}

	/**
	 * @return true if currently disbanding
	 */
	public boolean isDisbanding()
	{
		if (disbandTime > 0)
		{
			return true;
		}
		return false;
	}

	/**
	 * @param legionEmblem
	 *            the legionEmblem to set
	 */
	public void setLegionEmblem(LegionEmblem legionEmblem)
	{
		this.legionEmblem = legionEmblem;
	}

	/**
	 * @return the legionEmblem
	 */
	public LegionEmblem getLegionEmblem()
	{
		return legionEmblem;
	}

	/**
	 * @param legionWarehouse
	 *            the legionWarehouse to set
	 */
	public void setLegionWarehouse(LegionWarehouse legionWarehouse)
	{
		this.legionWarehouse = legionWarehouse;
	}

	/**
	 * @return the legionWarehouse
	 */
	public LegionWarehouse getLegionWarehouse()
	{
		return legionWarehouse;
	}

	/**
	 * Get warehouse slots
	 * 
	 * @return warehouse slots
	 */
	public int getWarehouseSlots()
	{
		switch (getLegionLevel())
		{
			case 1:
				return 24;
			case 2:
				return 32;
			case 3:
				return 40;
			case 4:
				return 48;
			case 5:
				return 56;
		}
		return 24;
	}

	/**
	 * @return the legionHistory
	 */
	public Collection<LegionHistory> getLegionHistory()
	{
		return this.legionHistory;
	}

	/**
	 * @param history
	 */
	public void addHistory(LegionHistory history)
	{
		this.legionHistory.add(history);
	}

	@Override
	public void getReward(Npc owner)
	{
	}

	@Override
	public void deleteTeam()
	{
		updateAfterDisbandLegion();
		DAOManager.getDAO(LegionDAO.class).deleteLegion(getObjectId());
		membersByName.clear();
		super.deleteTeam();
	}

	private void updateAfterDisbandLegion()
	{
		for (Player onlineLegionMember : getOnlineMembers())
		{
			PacketSendUtility.broadcastPacket(onlineLegionMember, new SM_LEGION_UPDATE_TITLE(onlineLegionMember.getObjectId()), true);
			PacketSendUtility.sendPacket(onlineLegionMember, new SM_LEGION_LEAVE_MEMBER(1300302, 0, getName()));
			onlineLegionMember.setLegion(null);
		}
	}

	@Override
	public boolean isFull()
	{
		switch (getLegionLevel())
		{
			case 1:
				if (size() < LegionConfig.LEGION_LEVEL1_MAX_MEMBERS)
					return false;
				break;
			case 2:
				if (size() < LegionConfig.LEGION_LEVEL2_MAX_MEMBERS)
					return false;
				break;
			case 3:
				if (size() < LegionConfig.LEGION_LEVEL3_MAX_MEMBERS)
					return false;
				break;
			case 4:
				if (size() < LegionConfig.LEGION_LEVEL4_MAX_MEMBERS)
					return false;
				break;
			case 5:
				if (size() < LegionConfig.LEGION_LEVEL5_MAX_MEMBERS)
					return false;
				break;
		}
		return true;
	}

	@Override
	public String getName()
	{
		return legionName;
	}

	@Override
	public LegionMember getLeader()
	{
		return getMemberById(leader);
	}

	private Legion getThis()
	{
		return this;
	}

	public void invitePlayerToLegion(final Player activePlayer, final Player targetPlayer)
	{
		if (targetPlayer != null)
		{
			if (targetPlayer.getPlayerSettings().isInDeniedStatus(DeniedStatus.GUILD))
			{
				PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.STR_MSG_REJECTED_INVITE_GUILD(targetPlayer.getName()));
				return;
			}
			if (canInvitePlayer(getMemberById(activePlayer.getObjectId()), targetPlayer))
			{
				RequestResponseHandler responseHandler = new RequestResponseHandler(activePlayer)
				{

					@Override
					public void acceptRequest(VisibleObject requester, Player responder)
					{
						if (!targetPlayer.getObjectTemplate().isOnline())
						{
							PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_INCORRECT_TARGET());
						}
						else
						{
							if (addLegionMember(targetPlayer))
							{
								// Tell all legion members a player joined the legion
								PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.NEW_MEMBER_JOINED(targetPlayer.getName()));

								// Display current announcement
								displayLegionMessage(targetPlayer, getCurrentAnnouncement());

								// Add to history of legion
								addHistory(targetPlayer.getName(), eLegionHistoryType.JOIN);
							}
							else
							{
								PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CAN_NOT_ADD_MEMBER_ANY_MORE());
							}
						}

					}

					@Override
					public void denyRequest(VisibleObject requester, Player responder)
					{
						PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.REJECTED_INVITE_REQUEST(targetPlayer.getName()));
					}
				};

				boolean requested = targetPlayer.getResponseRequester().putRequest(SM_QUESTION_WINDOW.STR_LEGION_INVITE, responseHandler);
				// If the player is busy and could not be asked
				if (!requested)
				{
					PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_TARGET_BUSY());
				}
				else
				{
					PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.SEND_INVITE_REQUEST(targetPlayer.getName()));

					// Send question packet to buddy
					PacketSendUtility.sendPacket(targetPlayer, new SM_QUESTION_WINDOW(SM_QUESTION_WINDOW.STR_LEGION_INVITE, 0, getName(),
							getLegionLevel() + "", activePlayer.getName()));
				}
			}
		}
		else
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_NO_USER_TO_INVITE());
		}
	}

	private boolean canInvitePlayer(LegionMember inviter, Player targetPlayer)
	{
		if (inviter.getPlayer().getLifeStats().isAlreadyDead())
		{
			PacketSendUtility.sendPacket(inviter.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_CANT_INVITE_WHILE_DEAD());
			return false;
		}
		if (inviter.equals(targetPlayer))
		{
			PacketSendUtility.sendPacket(inviter.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_CAN_NOT_INVITE_SELF());
			return false;
		}
		else if (targetPlayer.getLegion() != null)
		{
			if (targetPlayer.getLegion().equals(this))
			{
				PacketSendUtility.sendPacket(inviter.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_HE_IS_MY_GUILD_MEMBER(targetPlayer.getName()));
			}
			else
			{
				PacketSendUtility.sendPacket(inviter.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_HE_IS_OTHER_GUILD_MEMBER(targetPlayer.getName()));
			}
			return false;
		}
		else if (!inviter.hasRights(eLegionRight.INVITE))
		{
			//TODO retail message
			PacketSendUtility.sendMessage(inviter.getPlayer(), "You haven't rights to invite");
			return false;
		}
		else if (inviter.getCommondata().getRace() != targetPlayer.getObjectTemplate().getRace() && !LegionConfig.LEGION_INVITEOTHERFACTION)
		{
			//TODO need this?
			return false;
		}
		return true;
	}

	public void appointBrigadeGeneral(final Player activePlayer, final Player targetPlayer)
	{
		if (targetPlayer != null)
		{
			final LegionMember legionMember = getMemberById(targetPlayer.getObjectId());
			final LegionMember oldLeader = getMemberById(activePlayer.getObjectId());
			if (canAppointBrigadeGeneral(oldLeader, legionMember))
			{
				RequestResponseHandler responseHandler = new RequestResponseHandler(activePlayer)
				{

					@Override
					public void acceptRequest(VisibleObject requester, Player responder)
					{
						if (!targetPlayer.getObjectTemplate().isOnline())
						{
							PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGE_MASTER_NO_SUCH_USER());
						}
						else
						{
							if (legionMember.getRank().getRankId() > LegionRank.BRIGADE_GENERAL.getRankId())
							{
								// Demote Brigade General to Centurion
								oldLeader.setRank(LegionRank.CENTURION);
								oldLeader.updateInfo(responder.getLegion());
								DAOManager.getDAO(LegionDAO.class).updateLegionMember(oldLeader);
								// Promote member to Brigade General
								legionMember.setRank(LegionRank.BRIGADE_GENERAL);
								legionMember.updateInfo(responder.getLegion(), 1300273, targetPlayer.getName());
								DAOManager.getDAO(LegionDAO.class).updateLegionMember(legionMember);
								addHistory(targetPlayer.getName(), eLegionHistoryType.APPOINTED);
							}
						}
					}

					@Override
					public void denyRequest(VisibleObject requester, Player responder)
					{
						PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGE_MASTER_HE_DECLINE_YOUR_OFFER(targetPlayer.getName()));
					}
				};

				boolean requested = targetPlayer.getResponseRequester().putRequest(SM_QUESTION_WINDOW.STR_LEGION_CHANGE_MASTER, responseHandler);
				// If the player is busy and could not be asked
				if (!requested)
				{
					PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGE_MASTER_SENT_CANT_OFFER_WHEN_HE_IS_QUESTION_ASKED());
				}
				else
				{
					PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGE_MASTER_SENT_OFFER_MSG_TO_HIM(targetPlayer.getName()));
					// Send question packet to buddy
					PacketSendUtility.sendPacket(targetPlayer, new SM_QUESTION_WINDOW(SM_QUESTION_WINDOW.STR_LEGION_CHANGE_MASTER, activePlayer.getObjectId(), targetPlayer.getName()));
				}
			}
		}
		else
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGE_MASTER_NO_SUCH_USER());
		}
	}

	private boolean canAppointBrigadeGeneral(LegionMember activePlayer, LegionMember targetPlayer)
	{
		if (!activePlayer.isBrigadeGeneral())
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_CHANGE_MEMBER_RANK_DONT_HAVE_RIGHT());
			return false;
		}
		if (activePlayer.equals(targetPlayer))
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_CHANGE_MASTER_ERROR_SELF());
			return false;
		}
		else if (!isMember(getMemberById(targetPlayer.getObjectId())))
			// not in same legion
			return false;
		return true;
	}

	public void appointRank(Player activePlayer, Player targetPlayer, int rank)
	{
		if (targetPlayer != null)
		{
			final LegionMember legionMember = getMemberById(targetPlayer.getObjectId());
			final LegionMember oldLeader = getMemberById(activePlayer.getObjectId());
			if (canAppointRank(oldLeader, legionMember))
			{
				int msgId;
				if (rank == LegionRank.CENTURION.getRankId() && legionMember.getRank() == LegionRank.LEGIONARY)
				{
					// Change rank and define needed msg id
					legionMember.setRank(LegionRank.CENTURION);
					msgId = 1300267;
				}
				else
				{
					// Change rank and define needed msg id
					legionMember.setRank(LegionRank.LEGIONARY);
					msgId = 1300268;
				}
				DAOManager.getDAO(LegionDAO.class).updateLegionMember(legionMember);
				getMemberById(targetPlayer.getObjectId()).updateInfo(this, msgId, targetPlayer.getName());
			}
		}
		else
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGE_MEMBER_RANK_NO_USER());
		}
	}

	private boolean canAppointRank(LegionMember activePlayer, LegionMember targetPlayer)
	{
		if (!activePlayer.isBrigadeGeneral())
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_CHANGE_MEMBER_RANK_DONT_HAVE_RIGHT());
			return false;
		}
		if (activePlayer.equals(targetPlayer))
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_CHANGE_MEMBER_RANK_ERROR_SELF());
			return false;
		}
		else if (!isMember(targetPlayer))
		{
			// not in same legion
			return false;
		}
		return true;
	}

	public void changeNickname(String charName, String newNickname)
	{
		LegionMember legionMember = getMemberByName(charName);
		if (legionMember.setNickname(newNickname))
		{
			DAOManager.getDAO(LegionDAO.class).updateLegionMember(legionMember);
			PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_UPDATE_NICKNAME(legionMember.getObjectId(), newNickname));
		}
	}

	public void changeAnnouncement(Player activePlayer, String announcement)
	{
		LegionMember member = getMemberById(activePlayer.getObjectId());
		if (LegionConfig.ANNOUNCEMENT_PATTERN.matcher(announcement).matches() && member.hasRights(eLegionRight.ANNOUNCEMENT))
		{
			Timestamp currentTime = new Timestamp(System.currentTimeMillis());
			DAOManager.getDAO(LegionDAO.class).saveNewAnnouncement(this.getObjectId(), currentTime, announcement);
			addAnnouncementToList(currentTime, announcement);
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_WRITE_NOTICE_DONE());
			PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_EDIT(eLegionEditEvent.CHANGE_ANNOUNCEMENT,
					(int) (System.currentTimeMillis() / 1000), announcement));
			PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_INFO(this));
		}
	}

	public void changeSelfIntro(String charName, String newSelfIntro)
	{
		if (LegionConfig.SELF_INTRO_PATTERN.matcher(newSelfIntro).matches())
		{
			LegionMember legionMember = getMemberByName(charName);
			legionMember.setSelfIntro(newSelfIntro);
			DAOManager.getDAO(LegionDAO.class).updateLegionMember(legionMember);
			PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_UPDATE_SELF_INTRO(legionMember.getObjectId(), newSelfIntro));
			if (legionMember.getPlayer() != null)
				PacketSendUtility.sendPacket(legionMember.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_WRITE_INTRO_DONE());
		}
	}

	public void updateLevel(Player activePlayer)
	{
		if (canChangeLevel(activePlayer, activePlayer.getInventory().getKinahItem().getItemCount()))
		{
			Item.decreaseKinah(activePlayer, getKinahPrice());
			legionLevel += 1;
			PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_EDIT(eLegionEditEvent.CHANGE_LEVEL, this));
			PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_INFO(this));
			PacketSendUtility.broadcastPacketToTeam(null, this, SM_SYSTEM_MESSAGE.LEGION_LEVEL_UP(getLegionLevel()));
			DAOManager.getDAO(LegionDAO.class).storeLegion(this);
			addHistory(getLegionLevel() + "", eLegionHistoryType.LEVEL_UP);
		}
	}

	private boolean canChangeLevel(Player activePlayer, long kinahAmount)
	{
		int levelContributionPrice = getContributionPrice();

		if (getLegionLevel() == 5)
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGE_LEVEL_CANT_LEVEL_UP());
			return false;
		}
		else if (activePlayer.getInventory().getKinahItem().getItemCount() < getKinahPrice())
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGE_LEVEL_NOT_ENOUGH_KINAH());
			return false;
		}
		else if (!hasRequiredMembers())
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGE_LEVEL_NOT_ENOUGH_MEMBER());
			return false;
		}
		else if (getContributionPoints() < levelContributionPrice)
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGE_LEVEL_NOT_ENOUGH_POINT());
			return false;
		}
		return true;
	}

	private void displayLegionMessage(Player targetPlayer, Entry<Timestamp, String> currentAnnouncement)
	{
		if (currentAnnouncement != null)
		{
			PacketSendUtility.sendPacket(targetPlayer,
					SM_SYSTEM_MESSAGE.LEGION_DISPLAY_ANNOUNCEMENT(currentAnnouncement.getValue(), (int) (currentAnnouncement.getKey().getTime() / 1000), 2));
		}
	}

	public void storeLegionEmblem(Player activePlayer, byte version, boolean isUserEmblem, int color_rgb)
	{
		if (canStoreLegionEmblem(activePlayer, version))
		{
			if (getLegionEmblem().isDefaultEmblem())
				addHistory("", eLegionHistoryType.EMBLEM_REGISTER);
			else
				addHistory("", eLegionHistoryType.EMBLEM_MODIFIED);
			Item.decreaseKinah(activePlayer, LegionConfig.LEGION_EMBLEM_REQUIRED_KINAH);
			getLegionEmblem().setEmblem(version, isUserEmblem, color_rgb);
			PacketSendUtility.broadcastPacketToTeam(null, this, new SM_LEGION_UPDATE_EMBLEM(this, getLegionEmblem()));
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGED_EMBLEM());
			DAOManager.getDAO(LegionDAO.class).storeLegionEmblem(this.getObjectId(), legionEmblem);
		}
	}

	private boolean canStoreLegionEmblem(Player activePlayer, int emblemId)
	{
		final int MIN_EMBLEM_ID = 0;
		final int MAX_EMBLEM_ID = 40;

		Legion legion = activePlayer.getLegion();
		if (emblemId < MIN_EMBLEM_ID || emblemId > MAX_EMBLEM_ID)
		{
			// Not a valid emblemId
			return false;
		}
		else if (legion.getLegionLevel() < 2)
		{
			// legion level not high enough
			return false;
		}
		else if (activePlayer.getInventory().getKinahItem().getItemCount() < LegionConfig.LEGION_EMBLEM_REQUIRED_KINAH)
		{
			PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.NOT_ENOUGH_KINAH(LegionConfig.LEGION_EMBLEM_REQUIRED_KINAH));
			return false;
		}
		return true;
	}

	public void recreateLegion(VisibleObject npc, Player activePlayer)
	{
		if (canRecreateLegion(getMemberById(activePlayer.getObjectId())))
		{
			RequestResponseHandler disbandResponseHandler = new RequestResponseHandler(npc)
			{

				@Override
				public void acceptRequest(VisibleObject requester, Player responder)
				{
					setDisbandTime(0);
					PacketSendUtility.broadcastPacketToTeam(null, getThis(), new SM_LEGION_EDIT(eLegionEditEvent.RECOVER_LEGION));
					for (Player memb : getOnlineMembers())
						getMemberById(memb.getObjectId()).updateInfo(getThis(), 1300307, "");
				}

				@Override
				public void denyRequest(VisibleObject requester, Player responder)
				{
					// no message
				}
			};

			boolean disbandResult = activePlayer.getResponseRequester().putRequest(SM_QUESTION_WINDOW.STR_LEGION_DISBAND_CANCEL, disbandResponseHandler);
			if (disbandResult)
			{
				PacketSendUtility.sendPacket(activePlayer, new SM_QUESTION_WINDOW(SM_QUESTION_WINDOW.STR_LEGION_DISBAND_CANCEL, 0));
			}
		}
	}

	private boolean canRecreateLegion(LegionMember activePlayer)
	{
		if (!activePlayer.isBrigadeGeneral())
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_DISPERSE_ONLY_MASTER_CAN_DISPERSE());
			return false;
		}
		else if (!isDisbanding())
		{
			// Legion is not disbanding
			return false;
		}
		return true;
	}

	public void sendEmblem(Player player)
	{
		PacketSendUtility.sendPacket(player, new SM_LEGION_EMBLEM_INFO(getObjectId(), getName(), legionEmblem, true));
		if (legionEmblem.getUploadData() == null || legionEmblem.getUploadData().length == 0)
			return;
		ByteBuffer buf = ByteBuffer.allocate(getLegionEmblem().getUploadData().length);
		buf.put(getLegionEmblem().getUploadData()).position(0);
		int maxSize = 7993;
		byte[] bytes;
		while (buf.hasRemaining())
		{
			if (buf.remaining() >= maxSize)
			{
				bytes = new byte[maxSize];
			}
			else
			{
				bytes = new byte[buf.remaining()];
			}
			buf.get(bytes);
			PacketSendUtility.sendPacket(player, new SM_LEGION_EMBLEM_SHOW(bytes));
		}
	}

	public void uploadEmblemData(Player activePlayer, int size, byte[] data)
	{
		if (canUploadEmblem(getMemberById(activePlayer.getObjectId())))
		{
			LegionEmblem legionEmblem = getLegionEmblem();
			if (legionEmblem.addUploadData(data))
			{
				legionEmblem.setVersion((byte) (legionEmblem.getVersion() + 1));
				legionEmblem.setUserEmblem(true);
				legionEmblem.resetUploadSettings();
				legionEmblem.setPersistentState(PersistentState.UPDATE_REQUIRED);
				if (getLegionEmblem().isDefaultEmblem())
					addHistory("", eLegionHistoryType.EMBLEM_REGISTER);
				else
					addHistory("", eLegionHistoryType.EMBLEM_MODIFIED);
				Item.decreaseKinah(activePlayer, LegionConfig.LEGION_EMBLEM_REQUIRED_KINAH);
				setLegionEmblem(legionEmblem);
				for (Player player : getOnlineMembers())
					sendEmblem(player);
				PacketSendUtility.sendPacket(activePlayer, SM_SYSTEM_MESSAGE.LEGION_CHANGED_EMBLEM());
				DAOManager.getDAO(LegionDAO.class).storeLegionEmblem(getObjectId(), legionEmblem);
			}
		}
	}

	private boolean canUploadEmblem(LegionMember activePlayer)
	{
		if (!activePlayer.isBrigadeGeneral())
		{
			// Not legion leader
			return false;
		}
		else if (getLegionLevel() < 3)
		{
			// Legion level isn't high enough
			return false;
		}
		else if (!getLegionEmblem().isUploading())
		{
			// Not uploading emblem
			return false;
		}
		return true;
	}

	@Override
	public LegionMember getMemberById(int id)
	{
		return members.get(id);
	}

	public LegionMember getMemberByName(String name)
	{
		return membersByName.get(name.toLowerCase());
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.team.Team#addMember(com.aionemu.gameserver.model.team.interfaces.ITeamMember)
	 */
	@Override
	protected void addMember(LegionMember member)
	{
		membersByName.put(member.getCommondata().getName().toLowerCase(), member);
		super.addMember(member);
	}

	public void disbandLegion()
	{
		int unixTime = (int) ((System.currentTimeMillis() / 1000) + LegionConfig.LEGION_DISBAND_TIME);
		setDisbandTime(unixTime);
		PacketSendUtility.broadcastPacketToTeam(null, getThis(), new SM_LEGION_EDIT(eLegionEditEvent.DISBAND_LEGION, unixTime));
		for (Player onlineLegionMember : getOnlineMembers())
			getMemberById(onlineLegionMember.getObjectId()).updateInfo(this, 1300303, Integer.toString(unixTime));
	}

	public void requestDisbandLegion(VisibleObject npc, Player activePlayer)
	{
		if (canDisbandLegion(getMemberById(activePlayer.getObjectId())))
		{
			RequestResponseHandler disbandResponseHandler = new RequestResponseHandler(npc)
			{
				@Override
				public void acceptRequest(VisibleObject requester, Player responder)
				{
					disbandLegion();
				}

				@Override
				public void denyRequest(VisibleObject requester, Player responder)
				{
					// no message
				}
			};

			boolean disbandResult = activePlayer.getResponseRequester().putRequest(SM_QUESTION_WINDOW.STR_LEGION_DISBAND, disbandResponseHandler);
			if (disbandResult)
			{
				PacketSendUtility.sendPacket(activePlayer, new SM_QUESTION_WINDOW(SM_QUESTION_WINDOW.STR_LEGION_DISBAND, 0));
			}
		}
	}

	private boolean canDisbandLegion(LegionMember activePlayer)
	{
		// TODO: Can't disband during a war!!
		// TODO: Can't disband legion with fortress or hideout!!
		if (!activePlayer.isBrigadeGeneral())
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_DISPERSE_ONLY_MASTER_CAN_DISPERSE());
			return false;
		}
		else if (getLegionWarehouse().size() > 0)
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_DISPERSE_CANT_DISPERSE_GUILD_STORE_ITEM_IN_WAREHOUSE());
			return false;
		}
		else if (isDisbanding())
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_DISPERSE_ALREADY_REQUESTED());
			return false;
		}
		return true;
	}

	@Override
	public void onMemberLogIn(int objectId)
	{
		LegionMember member = members.get(objectId);
		member.getPlayer().setLegion(this);
		addOnlineMember(member.getPlayer());
		// Send Legion add member packet
		PacketSendUtility.sendPacket(member.getPlayer(), new SM_LEGION_ADD_MEMBER(member.getPlayer(), true, 0, ""));

		// Send legion info packets
		PacketSendUtility.sendPacket(member.getPlayer(), new SM_LEGION_INFO(this));

		// Tell all legion members player has come online
		member.updateInfo(this);

		// Notify legion members player has logged in
		PacketSendUtility.broadcastPacketToTeam(member.getPlayer(), this, SM_SYSTEM_MESSAGE.STR_MSG_NOTIFY_LOGIN_GUILD(member.getPlayer().getName()));

		// Send member add to player
		//PacketSendUtility.sendPacket(member.getPlayer(), new SM_LEGION_ADD_MEMBER(member.getPlayer(), true, 0, ""));

		// Send member list to player
		PacketSendUtility.sendPacket(member.getPlayer(), new SM_LEGION_MEMBERLIST(getMemberList()));

		// Send current announcement to player
		displayLegionMessage(member.getPlayer(), getCurrentAnnouncement());

		if (isDisbanding())
			PacketSendUtility.sendPacket(member.getPlayer(), new SM_LEGION_EDIT(eLegionEditEvent.DISBAND_LEGION, getDisbandTime()));
	}

	private Collection<LegionMember> getMemberList()
	{
		return members.values();
	}

	@Override
	public void onMemberLogOut(int memberId)
	{
		LegionMember member = members.get(memberId);
		member.updateInfo(this);
		member.getPlayer().setLegion(null);
		super.onMemberLogOut(memberId);
	}

	public void openLegionWarehouse(Player activePlayer, int targetObjectId)
	{
		if (canOpenWarehouse(getMemberById(activePlayer.getObjectId())))
		{
			PacketSendUtility.sendPacket(activePlayer, new SM_DIALOG_WINDOW(targetObjectId, 25));
			FastList<Item> items = new FastList<Item>();
			items.addAll(getLegionWarehouse().getStorageItems());
			int whSize = getLegionLevel() - 1;
			int itemsSize = items.size();

			boolean firstPacket = true;
			if (itemsSize != 0)
			{
				int index = 0;
				while (index + 10 < itemsSize)
				{
					PacketSendUtility.sendPacket(activePlayer, new SM_WAREHOUSE_INFO(items.subList(index, index + 10), StorageType.LEGION_WAREHOUSE.getId(),
							whSize, firstPacket));
					index += 10;
					firstPacket = false;
				}
				PacketSendUtility.sendPacket(activePlayer, new SM_WAREHOUSE_INFO(items.subList(index, itemsSize), StorageType.LEGION_WAREHOUSE.getId(), whSize,
						firstPacket));
			}
			PacketSendUtility.sendPacket(activePlayer, new SM_WAREHOUSE_INFO(null, StorageType.LEGION_WAREHOUSE.getId(), whSize, false));
		}
	}

	private boolean canOpenWarehouse(LegionMember activePlayer)
	{
		if (!activePlayer.hasRights(eLegionRight.WAREHOUSE))
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.GUILD_WAREHOUSE_NO_RIGHT);
			return false;
		}
		else if (isDisbanding())
		{
			PacketSendUtility.sendPacket(activePlayer.getPlayer(), SM_SYSTEM_MESSAGE.LEGION_WAREHOUSE_CANT_USE_WHILE_DISPERSE());
			return false;
		}
		return true;
	}

	/* (non-Javadoc)
	 * @see com.aionemu.gameserver.model.team.interfaces.ITeamMember#getRace()
	 */
	@Override
	public Race getRace()
	{
		return this.getLeader().getCommondata().getRace();
	}
}
